package com.zrwl.poscloud.core.annotion.AuthorityVerify;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.internal.LinkedTreeMap;
import com.zrwl.poscloud.base.entity.Admin;
import com.zrwl.poscloud.base.entity.AdminRole;
import com.zrwl.poscloud.base.entity.Menus;
import com.zrwl.poscloud.base.entity.Role;
import com.zrwl.poscloud.base.enums.EMenuType;
import com.zrwl.poscloud.base.enums.EStatus;
import com.zrwl.poscloud.base.global.ECode;
import com.zrwl.poscloud.commons.feign.ServerCenterFeignClient;
import com.zrwl.poscloud.commons.utils.JsonUtils;
import com.zrwl.poscloud.commons.utils.RedisUtil;
import com.zrwl.poscloud.commons.utils.ResultUtil;
import com.zrwl.poscloud.commons.utils.StringUtils;
import com.zrwl.poscloud.core.config.admin.LocalApiConfig;
import com.zrwl.poscloud.core.global.SQLConf;
import com.zrwl.poscloud.xo.global.MessageConf;
import com.zrwl.poscloud.xo.global.RedisConf;
import com.zrwl.poscloud.xo.global.SysConf;
import com.zrwl.poscloud.xo.service.*;
import com.zrwl.poscloud.xo.vo.AdminVO;
import com.zrwl.poscloud.xo.vo.MenusVO;
import com.zrwl.poscloud.xo.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 权限校验 切面实现
 *
 * @author: liusitong
 * @create: 2020-03-06-19:05
 */
@Aspect
@Component
@Slf4j
public class AuthorityVerifyAspect {

    @Autowired
    MenusService menusService;

    @Autowired
    RoleService roleService;

    @Autowired
    AdminService adminService;
    @Autowired
    UserService userService;

    @Autowired
    AdminRoleService adminRoleService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    LocalApiConfig localApiConfig;
    @Resource
    private ServerCenterFeignClient serverCenterFeignClient;

    @Pointcut(value = "@annotation(authorityVerify)")
    public void pointcut(AuthorityVerify authorityVerify) {

    }

    @Around(value = "pointcut(authorityVerify)")
    public Object doAround(ProceedingJoinPoint joinPoint, AuthorityVerify authorityVerify) throws Throwable {

        ServletRequestAttributes attribute = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attribute.getRequest();

        //获取请求路径
        String url = request.getRequestURI();

        // 解析出请求者的ID和用户名
        String ownerUid;
        if(request.getAttribute(SysConf.ADMIN_UID) == null){
            ownerUid = request.getHeader(SysConf.ADMIN_UID);
        }else {
            ownerUid = request.getAttribute(SysConf.ADMIN_UID).toString();
        }
        boolean isAdmin = true;
        // 管理员能够访问的路径
        String visitUrlStr = redisUtil.get(RedisConf.ADMIN_VISIT_MENU + RedisConf.SEGMENTATION + ownerUid);
        if (visitUrlStr == null) {
            // 管理员能够访问的路径
            visitUrlStr = redisUtil.get(RedisConf.USER_VISIT_MENU + RedisConf.SEGMENTATION + ownerUid);
            isAdmin = false;
        }
//        List<String> urlList = new ArrayList<>();
        LinkedTreeMap<String, String> visitMap = new LinkedTreeMap<>();

        if (StringUtils.isNotEmpty(visitUrlStr)) {
            // 从Redis中获取
            visitMap = (LinkedTreeMap<String, String>) JsonUtils.jsonToMap(visitUrlStr, String.class);
        }
        // 判断该角色是否能够访问该接口
        // 可以设置按钮权限为*  这样可以获取到全部按钮权限
        int buttonTag = url.lastIndexOf("/");
        String urlAll = url.substring(0, buttonTag) + "/*";
        if (StringUtils.isNotEmpty(visitUrlStr) && (visitMap.get(url) != null || visitMap.get(urlAll) != null || url.startsWith("/proxy/"))) {
            log.info("用户拥有操作权限，访问的路径: {}，拥有的权限接口：{}", url, visitMap.get(url));
            //执行业务
            //判断路径是不是需要给本地服务器进行转发
            if (localApiConfig.isLocalApi(url)) {
                JSONObject requestHeaderJson = new JSONObject();
                JSONObject requestParamJson = new JSONObject();
                for (Object arg : joinPoint.getArgs()) {
                    // request/response无法使用toJSON
                    if (arg instanceof HttpServletRequest) {
                    } else if (arg instanceof HttpServletResponse) {
                    } else if (arg instanceof BindingResult) {
                    } else {
                        JSONObject argJson = (JSONObject) JSONObject.toJSON(arg);
                        Iterator iterator = argJson.entrySet().iterator();
                        while (iterator.hasNext()) {
                            Map.Entry entry = (Map.Entry) iterator.next();
                            requestParamJson.put(entry.getKey().toString(), entry.getValue());
                        }
                    }
                }
                Enumeration headerNames = request.getHeaderNames();
                while (headerNames.hasMoreElements()) {
                    String paramName = (String) headerNames.nextElement();
                    if (paramName.equals("authorization")) {
                        requestHeaderJson.put("token", request.getHeader(paramName));
                    }
                }
                Enumeration paramNames = request.getParameterNames();
                while (paramNames.hasMoreElements()) {
                    String paramName = (String) paramNames.nextElement();
                    requestParamJson.put(paramName, request.getParameter(paramName));
                }
                String result = null;
                if (isAdmin) {
                    AdminVO me = adminService.getMe();
                    result = serverCenterFeignClient.proxyRequest("psms-core", me.getCompanyCode(), JSON.toJSONString(JSON.toJSON(me)), url, JSON.toJSONString(requestHeaderJson), JSON.toJSONString(requestParamJson));
                } else {
                    UserVO me = userService.getMe();
                    if (me.getEmployeeInfo() == null) {
                        throw new RuntimeException("禁止访问");
                    }
                    result = serverCenterFeignClient.proxyRequest("psms-core", me.getEmployeeInfo().getCompanyCode(), JSON.toJSONString(JSON.toJSON(me)), url, JSON.toJSONString(requestHeaderJson), JSON.toJSONString(requestParamJson));
                }

                return result;
            }
            return joinPoint.proceed();
        } else {
            log.info("用户不具有操作权限，访问的路径: {}", url);
            return ResultUtil.result(ECode.NO_OPERATION_AUTHORITY, MessageConf.RESTAPI_NO_PRIVILEGE);
        }
    }

}
